package com.fla.puzzle.ui.game;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import junit.framework.Assert;

import com.fla.puzzle.pack.PackItem;


/**
 * Describes game model.
 * 
 * 
 */
public class GameModel implements Serializable {
    private static final long serialVersionUID = -2778624721968329258L;
    
    private int rowsCount;
    private int colsCount;
    
    private PackItem packItem;
    
    // 1x1; 1x2; 1x3; 2x1 ....
    private List<GameField> orderedFields;

    public GameModel(int rowsCount, int colsCount, PackItem packItem) {
        Assert.assertNotNull(packItem);
        
        this.rowsCount = rowsCount;
        this.colsCount = colsCount;
        this.packItem = packItem;

        this.orderedFields = new ArrayList<GameField>(rowsCount * colsCount);

        for (int row = 0; row < rowsCount; row++) {
            for (int col = 0; col < colsCount; col++) {
                GameField point = new GameField(col, row);

                orderedFields.add(point);
            }
        }
    }

    public GameModel(int rowsCount, int colsCount, PackItem packItem, List<GameField> orderedFields) {
        this(rowsCount, colsCount, packItem);

        this.orderedFields = orderedFields;
    }

    /**
     * Tests if current game fields are in correct order. It means the game has been completed.
     * 
     * @return boolean true if all the fields are in correct order
     */
    public boolean areFieldsInCorrectOrder() {
        Iterator<GameField> gameFieldIterator = orderedFields.iterator();
        
        for (int row = 0; row < rowsCount; row++) {
            for (int col = 0; col < colsCount; col++) {
                GameField point = new GameField(col, row);

                if (!point.equals(gameFieldIterator.next())) {
                    return false;
                }
            }
        }
        return true;
    }
    
    /**
     * Swaps the given elements in model
     * 
     * @param position1 Point
     * @param position2 Point
     */
    public void swap(GameField position1, GameField position2) {
        int index1 = orderedFields.indexOf(position1);
        int index2 = orderedFields.indexOf(position2);
        
        Collections.swap(orderedFields, index1, index2);
    }

    public List<GameField> getOrderedFields() {
        return orderedFields;
    }
    
    public int getRowsCount() {
        return rowsCount;
    }

    public int getColsCount() {
        return colsCount;
    }

    public PackItem getPackItem() {
        return packItem;
    }

    @Override
    public String toString() {
        return String.format("GameModel: [rowsCount=%s; colsCount=%s; points=%s]", 
                rowsCount, colsCount, orderedFields.size());
    }
}
